/*
    服务端模块：将服务端的业务处理模块和网络模块进行融合，提供三种服务端：服务注册中心服务端RegistryServer、rpc服务端RpcServer、topic服务端TopicServer
    1、服务注册中心服务端：将业务层PDManager模块(rpc_registry.hpp)和网络层MuduoServer模块(net.hpp)进行融合，搭建一个服务注册中心服务器，提供服务管理功能
    2、rpc服务端：将业务层RpcRouter模块(rpc_router.hpp)、RegistryClient模块(rpc_client)和网络层MuduoServer模块(net.hpp)进行融合，搭建一个服务器，可以提供rpc调用服务
        同时也能够支持向服务注册中心注册上线的服务(由RegistryClient模块来完成)。同时使用者能够根据构造函数的参数决定是否开启RegistryClient模块
        如果开启，每次上线的方法也会被注册给服务注册中心，否则就是rpc客户端和服务端之间的通信
    3、topic服务端：将业务层PSManager模块(rpc_topic.hpp)和网络层MuduoServer模块(net.hpp)进行融合，搭建一个服务器，提供主题的发布与订阅服务
*/
#pragma once
#include "rpc_router.hpp"
#include "rpc_registry.hpp"
#include "rpc_topic.hpp"
#include "../common/dispatcher.hpp"
#include "../client/rpc_client.hpp"

namespace ns_jsonrpc
{
    namespace ns_server
    {
        // 服务注册中心服务端
        class RegistryServer
        {
        public:
            using RegistryServerPtr = std::shared_ptr<RegistryServer>;

        public:
            RegistryServer(int port) : _pd_manager(std::make_shared<PDManager>()),
                                       _dispatcher(std::make_shared<Dispatcher>()),
                                       _server(MuduoServerFactory::create(port))
            {
                // 设置回调
                // 1、设置服务注册/发现回调
                auto srvReqCallback = std::bind(&PDManager::onServiceRequest, _pd_manager.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerCallback<ServiceRequest>(MType::REQ_SERVICE, srvReqCallback);

                // 2、设置消息分发回调
                auto msgDispatchCallback = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(msgDispatchCallback);

                // 3、设置连接断闭回调（服务下线通知）
                auto connShutdownCallback = std::bind(&PDManager::onConnShutdown, _pd_manager.get(), std::placeholders::_1);
                _server->setCloseCallback(connShutdownCallback);
            }

            void start()
            {
                _server->start();
            }

        private:
            PDManager::PDManagerPtr _pd_manager;
            Dispatcher::DispatcherPtr _dispatcher;
            BaseServer::BaseServerPtr _server;
        };

        // rpc服务端
        class RpcServer
        {
        public:
            using RpcServerPtr = std::shared_ptr<RpcServer>;

        public:
            RpcServer(const Address &rpcServerHost, const Address &registryServerHost = Address(), bool enableDiscovery = false)
                : _enable_registry(enableDiscovery),
                  _rpc_server_host(rpcServerHost),
                  _router(std::make_shared<RpcRouter>()),
                  _dispatcher(std::make_shared<Dispatcher>())
            {
                // 设置回调
                // 1、rpc路由回调
                auto rpcRouterCallback = std::bind(&RpcRouter::onRpcRequest, _router.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerCallback<RpcRequest>(MType::REQ_RPC, rpcRouterCallback);

                // 2、消息分发回调
                _server = MuduoServerFactory::create(rpcServerHost.second);
                auto dispatcherCallback = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(dispatcherCallback);

                if (_enable_registry)
                {
                    // 启用了服务注册
                    _registry_client = std::make_shared<ns_client::RegistryClient>(registryServerHost.first, registryServerHost.second);
                }
            }

            void registerMethod(const ns_jsonrpc::ns_server::ServiceDescribe::ServiceDescribePtr &serviceDescribe)
            {
                // 开启了注册中心
                if (_enable_registry)
                    _registry_client->serviceRegistry(serviceDescribe->methodName(), _rpc_server_host);
                _router->registerMethod(serviceDescribe);
            }

            void start()
            {
                _server->start();
            }

        private:
            bool _enable_registry;         // 是否开启服务注册中心
            Address _rpc_server_host; // 服务注册中心地址
            ns_client::RegistryClient::RegistryClientPtr _registry_client;
            RpcRouter::RpcRouterPtr _router;
            Dispatcher::DispatcherPtr _dispatcher;
            BaseServer::BaseServerPtr _server;
        };

        // topic服务端
        class TopicServer
        {
        public:
            using TopicServerPtr = std::shared_ptr<TopicServer>;

        public:
            TopicServer(int port) : _ps_manager(std::make_shared<PSManager>()),
                                       _dispatcher(std::make_shared<Dispatcher>()),
                                       _server(MuduoServerFactory::create(port))
            {
                // 设置回调
                // 1、设置主题请求相关操作（创建/删除/订阅/取消订阅/发布）回调
                auto topicReqCallback = std::bind(&PSManager::onTopicRequest, _ps_manager.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerCallback<TopicRequest>(MType::REQ_TOPIC, topicReqCallback);

                // 2、设置消息分发回调
                auto msgDispatchCallback = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(msgDispatchCallback);

                // 3、设置连接断闭回调（订阅者下线时清理订阅者信息）
                auto connShutdownCallback = std::bind(&PSManager::onConnShutdown, _ps_manager.get(), std::placeholders::_1);
                _server->setCloseCallback(connShutdownCallback);
            }

            void start()
            {
                _server->start();
            }

        private:
            PSManager::PSManagerPtr _ps_manager;
            Dispatcher::DispatcherPtr _dispatcher;
            BaseServer::BaseServerPtr _server;
        };
    }
}
